/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package config;

import java.util.*;
import share.PGHelper;

/**
 *
 * @author Salm
 */
public class CFUrgentQuest implements JSONable {
    private static final Random randomer = new Random(System.currentTimeMillis());
    
    private int unlockLevel;
    private int nQuest;
    private long cooldown;
    private final NavigableMap<Integer, Pool> pools = new TreeMap();
    private List<Integer> questTimes;
    
    private CFUrgentQuest() {}
    public static CFUrgentQuest parse(Map<String, Object> json)
    {
        CFUrgentQuest uq = new CFUrgentQuest();
        uq.deser(json);
        
        return uq;
    }

    @Override
    public void deser(Map<String, Object> json) {
        this.unlockLevel = PGHelper.toInt(json.get("unlockLevel"));
        this.cooldown = 1000L * PGHelper.toLong(json.get("cooldown"));
        this.nQuest = PGHelper.toInt(json.get("nQuest"));
        
        this.deserQuestTimes((Map) json.get("questTimes"));
        this.deserPools((Map) json.get("pools"));
    }
    
    private void deserQuestTimes(Map<String, Object> json)
    {
        this.questTimes = new ArrayList(json.size());
        for (int i = 0; i < json.size(); ++i)
        {
            this.questTimes.add(null);
        }
        
        for (Map.Entry<String, Object> qTimeEntry : json.entrySet()) {
            int index = PGHelper.toInt(qTimeEntry.getKey());
            Integer qTime = PGHelper.toInt(qTimeEntry.getValue());
            
            this.questTimes.set(index, qTime);
        }
    }
    
    private void deserPools(Map<String, Object> json)
    {
        for (Map.Entry<String, Object> poolEntry : json.entrySet()) {
            Integer minLevel = PGHelper.toInt(poolEntry.getKey());
            
            Map<String, Object> poolJson = (Map) poolEntry.getValue();
            Pool pool = new Pool();
            pool.deser(poolJson);
            
            this.pools.put(minLevel, pool);
        }
    }

    public int getUnlockLevel() {
        return unlockLevel;
    }

    public long getCooldown() {
        return cooldown;
    }
    
    public int nQuest()
    {
        return nQuest;
    }
    
    public Pack randomQuest(int uLevel)
    {
        Integer minLvl = this.pools.floorKey(uLevel);
        if (minLvl == null)
            throw new IllegalArgumentException("Not engouh level");
        
        Pool pool = this.pools.get(minLvl);
        return pool.randPack();
    }
    
    public long randQuestTime()
    {
        return 1000L * this.questTimes.get(randomer.nextInt(this.questTimes.size()));
    }
    
    private static class Pool implements JSONable
    {
        private final NavigableMap<Integer, String> packRates = new TreeMap();
        private final Map<String, Pack> packs = new HashMap();
        private int totalPackRate = 0;
        
        @Override
        public void deser(Map<String, Object> json) {
            Map<String, Object> qJson = (Map) json.get("quests");
            
            totalPackRate = 0;
            for (Map.Entry<String, Object> entrySet : qJson.entrySet()) {
                String packID = entrySet.getKey();
                Object value = entrySet.getValue();
                
                Pack pack = new Pack();
                pack.deser((Map) value);
                
                int packRate = PGHelper.toInt(((Map) value).get("rate"));
                
                this.packRates.put(totalPackRate, packID);
                this.packs.put(packID, pack);
                
                totalPackRate += packRate;
            }
        }
        
        public Pack randPack()
        {
            int randVal = randomer.nextInt(totalPackRate);
            Integer randFloor = packRates.floorKey(randVal);
            
            if (randFloor != null)
            {
                return packs.get(packRates.get(randFloor));
            }
            
            return null;
        }
    }
    
    public static class Pack implements JSONable
    {
        private Map<String, Object> actionData;
        private Map<String, Object> prizeData;
        private Map<String, Object> totalPrizeData;
        
        private Pack() {}

        @Override
        public void deser(Map<String, Object> json) {
            this.actionData = Collections.unmodifiableMap((Map) json.get("actions"));
            this.prizeData = Collections.unmodifiableMap((Map) json.get("prizes"));
            this.totalPrizeData = Collections.unmodifiableMap((Map) json.get("totalPrizes"));
        }
        
        public Map<String, Object> randAction()
        {
            return (Map) MapProcessor.minMaxRandom(randomer, actionData);
        }
        
        public Map<String, Object> randPrize()
        {
            return (Map) MapProcessor.minMaxRandom(randomer, prizeData);
        }
        
        public Map<String, Object> getTotalPrize()
        {
            return totalPrizeData;
        }
    }
}
